package org.linlinjava.litemall.wx.web;

import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.user.XxlSsoUser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.annotations.Param;
import org.linlinjava.litemall.core.storage.StorageService;
import org.linlinjava.litemall.core.util.CharUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallDisputeOrder;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallOrderReport;
import org.linlinjava.litemall.db.domain.LitemallStorage;
import org.linlinjava.litemall.db.service.LitemallDisputeService;
import org.linlinjava.litemall.db.service.LitemallOrderReportService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.service.LitemallStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 对象存储服务
 */
@RestController
@RequestMapping("/wx/storage")
@Validated
public class WxStorageController {
    private final Log logger = LogFactory.getLog(WxStorageController.class);

    @Autowired
    private StorageService storageService;
    @Autowired
    private LitemallStorageService litemallStorageService;
    @Autowired
    private LitemallOrderReportService reportService;
    @Autowired
    private LitemallOrderService orderService;
    @Autowired
    private LitemallDisputeService disputeService;

    private String generateKey(String originalFilename) {
        int index = originalFilename.lastIndexOf('.');
        String suffix = originalFilename.substring(index);

        String key = null;
        LitemallStorage storageInfo = null;

        do {
            key = CharUtil.getRandomString(20) + suffix;
            storageInfo = litemallStorageService.findByKey(key);
        }
        while (storageInfo != null);

        return key;
    }

    /**
     *  上传图片:与商户的Storage 基本一致..
     * @param file  MultipartFile
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public Object upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
        String originalFilename = file.getOriginalFilename();
        LitemallStorage litemallStorage = storageService.store(file.getInputStream(), file.getSize(), file.getContentType(), originalFilename);
        if (litemallStorage == null) {
            return ResponseUtil.fail(403, "您上传的图片不合法，请稍后再试");
        }
        XxlSsoUser user = (XxlSsoUser)request.getAttribute(Conf.SSO_USER);
        String userId = user.getUserid();
                logger.info("(customer)userId: " + userId + ", uploadTime: " + new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss").format(new Date())
                + ", uploadFile: " + file.getOriginalFilename() + ", uploadSize: " + file.getSize());
        return ResponseUtil.ok(litemallStorage);
    }


    /**
     * 访问存储对象
     *
     * @param key 存储对象key
     * @return
     */
    @GetMapping("/fetch/{key:.+}")
    public ResponseEntity<Resource> fetch(@PathVariable String key) {
        LitemallStorage litemallStorage = litemallStorageService.findByKey(key);
        if (key == null) {
            return ResponseEntity.notFound().build();
        }
        if (key.contains("../")) {
            return ResponseEntity.badRequest().build();
        }
        String type = litemallStorage.getType();
        MediaType mediaType = MediaType.parseMediaType(type);

        Resource file = storageService.loadAsResource(key);
        if (file == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok().contentType(mediaType).body(file);
    }

    /**
     * 访问存储对象
     *
     * @param key 存储对象key
     * @return
     */
    @GetMapping("/download/{key:.+}")
    public ResponseEntity<Resource> download(@PathVariable String key) {
        LitemallStorage litemallStorage = litemallStorageService.findByKey(key);
        if (key == null) {
            return ResponseEntity.notFound().build();
        }
        if (key.contains("../")) {
            return ResponseEntity.badRequest().build();
        }

        String type = litemallStorage.getType();
        MediaType mediaType = MediaType.parseMediaType(type);

        Resource file = storageService.loadAsResource(key);
        if (file == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok().contentType(mediaType).header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + file.getFilename() + "\"").body(file);
    }

    /**
     * 访问特殊储存对象
     **/
    @GetMapping("/view")
    public ResponseEntity<Resource> view(@Param(value = "fileName") String fileName, HttpServletRequest request) {
        String type = fileName.split("_")[0];
        if ("report".equals(type)) {
            LitemallOrderReport storageInfo = reportService.findByName(fileName);
            if (storageInfo == null) {
                return ResponseEntity.notFound().build();
            }
            if ("order".equals(storageInfo.getType())) {
                LitemallOrder order = orderService.findById(storageInfo.getOrderId());
                XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
                String userId = user.getUserid();
                if (!order.getUserId().toString().equals(userId)) {
                    ResponseEntity.badRequest().build();
                }
                String realPath = System.getProperty("user.dir");
                File file = new File(realPath + "/report/" + fileName);
                try {
                    Path path = file.toPath();
                     String mimeType = Files.probeContentType(path);
                    Resource resource = new UrlResource(path.toUri());
                    return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).body(resource);
                } catch (IOException e) {
                    e.printStackTrace();
                    return ResponseEntity.notFound().build();
                }
            }
            else if ("dispute".equals(storageInfo.getType())) {
                LitemallDisputeOrder disputeOrder = disputeService.findOrderById(storageInfo.getOrderId());
                XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
                String userId = user.getUserid();
                if (!disputeOrder.getUserId().toString().equals(userId)) {
                    return ResponseEntity.badRequest().build();
                }
                String realPath = System.getProperty("user.dir");
                File file = new File(realPath + "/report/" + fileName);
                try {
                    Path path = file.toPath();
                     String mimeType = Files.probeContentType(path);
                    Resource resource = new UrlResource(path.toUri());
                    return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).body(resource);
                } catch (IOException e) {
                    e.printStackTrace();
                    return ResponseEntity.notFound().build();
                }
            }
        }
        else if ("bank".equals(type)) {
            LitemallOrder order = orderService.findByBankCertificate(fileName);
            LitemallDisputeOrder disOrder = disputeService.findByBankCertificate(fileName);
            if (order == null && disOrder == null) {
                return ResponseEntity.badRequest().build();
            }
            Integer orderUser = order == null ? disOrder.getUserId() : order.getUserId();
            XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
            String userId = user.getUserid();
            if (!orderUser.toString().equals(userId)) {
                ResponseEntity.badRequest().build();
            }
            String realPath = System.getProperty("user.dir");
            File file = new File(realPath + "/bankPay/" + fileName);
            try {
                Path path = file.toPath();
                 String mimeType = Files.probeContentType(path);
                Resource resource = new UrlResource(path.toUri());
                return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).body(resource);
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseEntity.notFound().build();
            }
        }
        else if ("license".equals(type)) {
            String realPath = System.getProperty("user.dir");
            File file = new File(realPath + "/license/" + fileName);
            try {
                Path path = file.toPath();
                String mimeType = Files.probeContentType(path);
                Resource resource = new UrlResource(path.toUri());
                return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).body(resource);
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseEntity.notFound().build();
            }
        }
        return ResponseEntity.badRequest().build();
    }

    /**
     * 下载特殊储存对象
     **/
    @GetMapping("/down")
    public ResponseEntity<Resource> down(@Param(value = "fileName") String fileName, HttpServletRequest request) {
        String type = fileName.split("_")[0];
        if ("report".equals(type)) {
            LitemallOrderReport storageInfo = reportService.findByName(fileName);
            if (storageInfo == null) {
                return ResponseEntity.notFound().build();
            }
            if ("order".equals(storageInfo.getType())) {
                LitemallOrder order = orderService.findById(storageInfo.getOrderId());
                XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
                String userId = user.getUserid();
                if (!order.getUserId().toString().equals(userId)) {
                    ResponseEntity.badRequest().build();
                }
                String realPath = System.getProperty("user.dir");
                File file = new File(realPath + "/report/" + fileName);
                try {
                    Path path = file.toPath();
                    String mimeType = Files.probeContentType(path);
                    Resource resource = new UrlResource(path.toUri());
                    return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).header(HttpHeaders.CONTENT_DISPOSITION,
                            "attachment; filename=\"" + file.getName() + "\"").body(resource);
                } catch (IOException e) {
                    e.printStackTrace();
                    return ResponseEntity.notFound().build();
                }
            } else if ("dispute".equals(storageInfo.getType())) {
                LitemallDisputeOrder disputeOrder = new LitemallDisputeOrder();
                XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
                String userId = user.getUserid();
                if (!disputeOrder.getUserId().toString().equals(userId)) {
                    return ResponseEntity.badRequest().build();
                }
                String realPath = System.getProperty("user.dir");
                File file = new File(realPath + "/report/" + fileName);
                try {
                    Path path = file.toPath();
                    String mimeType = Files.probeContentType(path);
                    Resource resource = new UrlResource(path.toUri());
                    return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).header(HttpHeaders.CONTENT_DISPOSITION,
                            "attachment; filename=\"" + file.getName() + "\"").body(resource);
                } catch (IOException e) {
                    e.printStackTrace();
                    return ResponseEntity.notFound().build();
                }
            }
        }
        else if ("bank".equals(type)) {
            LitemallOrder order = orderService.findByBankCertificate(fileName);
            LitemallDisputeOrder disOrder = disputeService.findByBankCertificate(fileName);
            if (order == null && disOrder == null) {
                return ResponseEntity.badRequest().build();
            }
            Integer orderUser = order == null ? disOrder.getUserId() : order.getUserId();
            XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
            String userId = user.getUserid();
            if (!orderUser.toString().equals(userId)) {
                ResponseEntity.badRequest().build();
            }
            String realPath = System.getProperty("user.dir");
            File file = new File(realPath + "/bankPay/" + fileName);
            try {
                Path path = file.toPath();
                String mimeType = Files.probeContentType(path);
                Resource resource = new UrlResource(path.toUri());
                return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + file.getName() + "\"").body(resource);
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseEntity.notFound().build();
            }
        }
        else if ("license".equals(type)) {
            //获取项目地址
            String realPath = System.getProperty("user.dir");
            File file = new File(realPath + "/license/" + fileName);
            try {
                Path path = file.toPath();
                String mimeType = Files.probeContentType(path);
                Resource resource = new UrlResource(path.toUri());
                return ResponseEntity.ok().contentType(MediaType.parseMediaType(mimeType)).header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment; filename=\"" + file.getName() + "\"").body(resource);
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseEntity.notFound().build();
            }
        }
        return ResponseEntity.badRequest().build();
    }
}
